package pyip.lib.mixtool.util;

public class BytesUtil {
    public static char hex(int b) {
        b &= 0xf;
        return (char) (b < 10 ? '0' + b : 'a' - 10 + b);
    }

    public static int h2b(char c) {
        if (c <= '9')
            return c - '0';
        if (c <= 'Z')
            return c - 'A' + 10;
        return c - 'a' + 10;
    }

    public static BytesKey keyOf(byte[] b) {
        return new BytesKey(b);
    }

    public static int hashCode(byte[] b) {
        return hashCode(b, 0, b.length);
    }

    public static int hashCode(byte[] b, int off, int len) {
        int h = 0;
        while (len-- > 0)
            h = h * 31 + b[off++];
        return h;
    }

    public static String toHexString(byte[] b, int off, int len) {
        StringBuilder sb = new StringBuilder();
        while (len-- > 0) {
            int v = b[off++];
            sb.append(hex(v >>> 4)).append(hex(v));
        }
        return sb.toString();
    }

    public static String toHexString(byte[] b) {
        if (b == null)
            return null;
        return toHexString(b, 0, b.length);
    }

    public static byte[] fromHexString(String text) {
        if (text == null)
            return null;
        byte[] b = new byte[text.length() / 2];
        int ii = 0;
        for (int i = 0; i < b.length; i++) {
            b[i] = (byte) ((h2b(text.charAt(ii++)) << 4) + h2b(text.charAt(ii++)));
        }
        return b;
    }

    public static boolean isEmpty(byte[] b) {
        return b == null || b.length == 0;
    }

    public static int compare(byte[] b1, byte[] b2) {
        if (isEmpty(b1))
            return isEmpty(b2) ? 0 : -1;
        if (isEmpty(b2))
            return 1;
        int len = Math.min(b1.length, b2.length);
        for (int i = 0; i < len; i++) {
            if (b1[i] != b2[i]) {
                return (0xff & b1[i]) - (0xff & b2[i]);
            }
        }
        return b1.length - b2.length;
    }

    public static boolean equals(byte[] b1, byte[] b2) {
        if (isEmpty(b1))
            return isEmpty(b2);
        if (isEmpty(b2))
            return false;
        if (b1.length != b2.length)
            return false;
        for (int i = 0; i < b1.length; i++)
            if (b1[i] != b2[i])
                return false;
        return true;
    }

    public static byte[] l2b(long val) {
        byte[] b = new byte[8];
        setLong(b, 0, val);
        return b;
    }

    public static long b2l(byte[] b) {
        return getLong(b, 0);
    }

    public static byte[] i2b(int val) {
        byte[] b = new byte[4];
        setInt(b, 0, val);
        return b;
    }

    public static int b2i(byte[] b) {
        return getInt(b, 0);
    }

    public static void setLong(byte[] b, int off, long val) {
        b[off++] = (byte) (val >>> 56);
        b[off++] = (byte) (val >>> 48);
        b[off++] = (byte) (val >>> 40);
        b[off++] = (byte) (val >>> 32);
        b[off++] = (byte) (val >>> 24);
        b[off++] = (byte) (val >>> 16);
        b[off++] = (byte) (val >>> 8);
        b[off] = (byte) (val);
    }

    public static long getLong(byte[] b, int off) {
        return ((0xffl & (long) b[off++]) << 56) | ((0xffl & (long) b[off++]) << 48) | ((0xffl & (long) b[off++]) << 40) | ((0xffl & (long) b[off++]) << 32)
                | ((0xffl & (long) b[off++]) << 24) | ((0xffl & (long) b[off++]) << 16) | ((0xffl & (long) b[off++]) << 8) | ((0xffl & (long) b[off]));
    }

    public static void setInt(byte[] b, int off, int val) {
        b[off++] = (byte) (val >>> 24);
        b[off++] = (byte) (val >>> 16);
        b[off++] = (byte) (val >>> 8);
        b[off] = (byte) (val);
    }

    public static int getInt(byte[] b, int off) {
        return ((0xff & (int) b[off++]) << 24) | ((0xff & (int) b[off++]) << 16) | ((0xff & (int) b[off++]) << 8) | ((0xff & (int) b[off]));
    }

    public static byte[] combinBytes(byte[]... bs) {
        int len = 0;
        for (byte[] b : bs)
            len += b.length;
        byte[] r = new byte[len];
        len = 0;
        for (byte[] b : bs) {
            System.arraycopy(b, 0, r, len, b.length);
            len += b.length;
        }
        return r;
    }
}
